package main

import (
	"./cale"
	"fmt"
	"math"
	"math/big"
	"regexp"
	"sync"
)

func main() {

	//regexp正则表达式包
	//正则表达式，通常简写为regexp是预先定义好的一个规则字符串
	//通过这个规则字符串可以匹配查找分割和替换那些符合规则的文本
	//正则表达式应用非常广泛

	//MatchString()函数，用于匹配字符串  func MatchString(expr string,s string)(matched bool,err error)  expr模板字符串，s是测试字符串，有效返回bool，无效返回error

	//声明目标字符串
	text1 := "我的邮箱是:492079786@qq.com"
	text2 := "我的另一个邮箱是:zyj20021104@gmail.com"

	//采用原始字符串表示正则表达式    限定符 ?:这个符号前面的字符可有可无 *匹配前面的字符可以没有也可以出现多次 +匹配出现一次以上的字符  {n}指定出现的次数n {n,m}次数出现n到m次
	//(ab)原子组     a (cat|dog)要么是a cat要么是a dog   [abc]+ 去出现过一次的abc之中的字符  .任意字符   ^a匹配行首的a   a$匹配行尾的a \d数字 \w字母 \s 空格或tab
	pattern := "我的邮箱是:\\d+@qq\\.com$"
	matched, err := regexp.MatchString(pattern, text1)
	println(matched, err)
	pattern2 := "我的另一个邮箱是:[a-z0-9]+@gmail\\.com"
	matched1, err1 := regexp.MatchString(pattern2, text2)
	println(matched1, err1)

	//编译正则表达式 再从文本中找出符合的字符串
	pattern3 := "\\d+@qq\\.com"
	compile, _ := regexp.Compile(pattern3)
	fmt.Println(compile.FindString(text1))
	pattern4 := "[a-zA-Z0-9]+@gmail\\.com"
	compile2 := regexp.MustCompile(pattern4) //对比Compile 这个方法不会返回error
	fmt.Println(compile2.FindString(text2))

	//锁和sync包
	//当不同线程要使用同一个变量时，经常会出现一个问题：无法预知变量被不同线程修改的顺序！
	//经典的做法是一次只能让一个线程对共享变量进行操作。当变量被一个线程改变时 (临界区)，我们为它上锁，直到这个线程执行完成并解锁后，其他线程才能访问它

	//sync.Mutex 是一个互斥锁，它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。
	mutex := sync.Mutex{}
	mutex.Lock()   //上锁操作
	mutex.Unlock() //解锁操作
	//sync.RWMutex是一个读写互斥锁，它提供了我们上面的刚刚看到的sync.Mutex的Lock和UnLock方法（因为这两个结构都实现了sync.Locker接口）
	//。但是，它还允许使用RLock和RUnlock方法进行并发读取 RLock()允许同一时间多个线程对变量进行读操作，但是只能一个线程进行写操作
	//sync.RWMutex允许至少一个读锁或一个写锁存在，而sync.Mutex允许一个读锁或一个写锁存在。

	//精密计算和 big 包
	//对于整数的高精度计算 Go 语言中提供了 big 包。其中包含了 math 包：有用来表示大整数的 big.Int
	//和表示大有理数的 big.Rat 类型（可以表示为 2/5 或 3.1416 这样的分数，而不是无理数或 π）。
	//这些类型可以实现任意位类型的数字，只要内存足够大。缺点是更大的内存和处理开销使它们使用起来要比内置的数字类型慢很多。

	//整数
	im := big.NewInt(math.MaxInt64) //math.MaxInt64最大int64的值
	in := im
	io := big.NewInt(1956)
	ip := big.NewInt(1)
	ip.Mul(im, in).Add(ip, im).Div(ip, io)
	fmt.Printf("Big Int: %v\n", ip)
	//分数
	rm := big.NewRat(math.MaxInt64, 1956)
	rn := big.NewRat(-1956, math.MaxInt64)
	ro := big.NewRat(19, 56)
	rp := big.NewRat(1111, 2222)
	rq := big.NewRat(1, 1)
	rq.Mul(rm, rn).Add(rq, ro).Mul(rq, rp)
	fmt.Printf("Big Rat: %v\n", rq)

	//包
	//包是多个go文件源码的集合，他是一种高级的复用方案
	//一个文件夹下面只能有一个包，同样的一个包的文件不能在多个文件夹
	//包名和文件夹名字不一样，包名不能用_符号
	//如果包的变量要被调用，首字母必须大写
	//包名为main包为应用的入口程序，编译时不含main包的不会得到可执行文件
	//匿名导入包 import _ "包路径"  这个导入方式适用于我们不适用包的数据，但是需要使用他出的初始化函数
	fmt.Print(cale.Name)
	cale.TestPackage()

}
